home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / audio / drive / Stretch.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  18.1 KB  |  747 lines

  1. /*
  2.  * Copyright 1992-1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. //////////////////////////////////////////////////////////////////////
  18. // Stretch.c++ - implementation of the stretch abstract class
  19. //
  20. // A road is made up of stretches of road. Each stretch
  21. // is of some type - straightaway, curve, loop, etc.
  22. //
  23. // This is the abstract base class from which all types
  24. // of stretches are derived.
  25. //////////////////////////////////////////////////////////////////////
  26.  
  27. #include "Stretch.h"
  28. #include "Render.h"
  29. #include "Car.h"
  30. #include "Dynamics.h"
  31. #include "MiscMath.h"
  32. #include "Scenery.h"
  33.  
  34. int Stretch::_ahead = 2; // number of stretches to draw ahead of this one
  35. int Stretch::_drawn = 0; // number of stretches drawn in current rendering
  36.  
  37.  
  38. Stretch::Stretch(Stretch *prev, Stretch *next)
  39. {
  40.  
  41.     _prev = prev;
  42.     _next = next;
  43.  
  44.     if (_prev)
  45.     {
  46.         if (_prev->get_next())
  47.             fprintf(stderr,"Previous stretch already has a next\n");
  48.             
  49.         _prev->set_next(this);
  50.     }
  51.     
  52.     if (_next)
  53.     {
  54.         if (_next->get_prev())
  55.             fprintf(stderr,"Next stretch already has a previous\n");
  56.  
  57.         _next->set_prev(this);
  58.     }
  59.  
  60.     // list of cars currently on this stretch
  61.     _car_list = new SbPList();
  62. }
  63.  
  64.  
  65. // modify step size to exactly match length/segment_count
  66. void Stretch::compute_step()
  67. {
  68.     _num_markers = (int)(_length/_step) + 1;
  69.     _step = _length/(float)(_num_markers - 1);
  70. }
  71.  
  72.  
  73. void Stretch::allocate_data()
  74. {
  75.     _data = new StretchData[_num_markers];
  76.     _median_data = new StretchData[_num_markers];
  77.     _left_terrain_data = new StretchData[_num_markers];
  78.     _right_terrain_data = new StretchData[_num_markers];
  79. }
  80.  
  81.  
  82. Stretch::~Stretch()
  83. {
  84. //    delete [_num_markers] _data;
  85. //    delete [_num_markers] _median_data;
  86. //    delete [_num_markers] _left_terrain_data;
  87. //    delete [_num_markers] _right_terrain_data;
  88.     delete [] _data;
  89.     delete [] _median_data;
  90.     delete [] _left_terrain_data;
  91.     delete [] _right_terrain_data;
  92. }
  93.  
  94.  
  95. // rotate the data and normals about the center of
  96. // the road by bank radians counter clockwise
  97. void Stretch::rotate_bank(int i, float bank)
  98. {
  99.     // axis to rotate about
  100.     SbVec3f horizontal = _data[i].right - _data[i].left;
  101.     SbVec3f axis = horizontal.cross(_data[i].normal);
  102.     axis.normalize();
  103.  
  104.     SbRotation bank_quat(axis,bank);
  105.     SbMatrix xform, trans_back, rot_bank;
  106.     
  107.     SbVec3f temp;
  108.  
  109.     // transform the left and right data points by translating
  110.     // them back to the origin (by middle data), rotating by bank,
  111.     // then translating back
  112.     xform.identity();
  113.     
  114.     xform.setTranslate(_data[i].middle);
  115.  
  116.     rot_bank.setRotate(bank_quat);
  117.     xform = xform.multLeft(rot_bank);
  118.     
  119.     trans_back.setTranslate(- _data[i].middle);
  120.     xform = xform.multLeft(trans_back);
  121.  
  122.  
  123.     // transform the points
  124.     temp = _data[i].left;
  125.     xform.multVecMatrix(temp,_data[i].left);
  126.  
  127.     temp = _data[i].right;
  128.     xform.multVecMatrix(temp,_data[i].right);
  129.  
  130.     // the normal only gets rotated
  131.     SbMatrix bank_mat;
  132.     bank_mat.setRotate(bank_quat);
  133.     temp = _data[i].normal;
  134.     bank_mat.multDirMatrix(temp,_data[i].normal);
  135. }
  136.  
  137.  
  138. void Stretch::find_previous(SbVec3f &prev_offset, SbRotation &prev_orientation)
  139. {
  140.     if (_prev)
  141.     {
  142.         prev_offset = _prev->get_offset();
  143.         prev_orientation = _prev->get_orientation();
  144.     }
  145.     else
  146.     {
  147.         SbVec3f up(0.0,1.0,0.0);
  148.         prev_offset.setValue(0.0,0.0,0.0);
  149.         prev_orientation.setValue(up,0.0);
  150.     }
  151. }
  152.  
  153.  
  154. // match up ends
  155. void Stretch::match_ends()
  156. {
  157.     
  158.     if (_prev)
  159.     {
  160.         _data[0].left = _prev->get_left(_prev->get_count() - 1);
  161.         _data[0].middle = _prev->get_middle(_prev->get_count() - 1);
  162.         _data[0].right = _prev->get_right(_prev->get_count() - 1);
  163.         _data[0].normal = _prev->get_normal(_prev->get_count() - 1);
  164.  
  165.         _median_data[0].left = _prev->get_left_median(_prev->get_count() - 1);
  166.         _median_data[0].right = _prev->get_right_median(_prev->get_count()- 1);
  167.         
  168.         _left_terrain_data[0].left = 
  169.             _prev->get_left_terrain(_prev->get_count()- 1).left;
  170.         _left_terrain_data[0].right = 
  171.             _prev->get_left_terrain(_prev->get_count()-1).right;
  172.  
  173.         _right_terrain_data[0].left = 
  174.             _prev->get_right_terrain(_prev->get_count()- 1).left;
  175.         _right_terrain_data[0].right = 
  176.             _prev->get_right_terrain(_prev->get_count()-1).right;
  177.     }
  178.  
  179.     if (_next)
  180.     {
  181.         _data[_num_markers - 1].left = _next->get_left(0);
  182.         _data[_num_markers - 1].middle = _next->get_middle(0);
  183.         _data[_num_markers - 1].right = _next->get_right(0);
  184.         _data[_num_markers - 1].normal = _next->get_normal(0);
  185.  
  186.         _median_data[_num_markers - 1].left = _next->get_left_median(0);
  187.         _median_data[_num_markers - 1].right = _next->get_right_median(0);
  188.         
  189.         _left_terrain_data[_num_markers - 1].left = 
  190.             _next->get_left_terrain(0).left;
  191.         _left_terrain_data[_num_markers - 1].right = 
  192.             _next->get_left_terrain(0).right;
  193.  
  194.         _right_terrain_data[_num_markers - 1].left = 
  195.             _next->get_right_terrain(0).left;
  196.         _right_terrain_data[_num_markers - 1].right = 
  197.             _next->get_right_terrain(0).right;
  198.     }
  199. }
  200.  
  201.  
  202. void Stretch::transform_data(SbVec3f prev_offset, SbRotation prev_orientation)
  203. {
  204.     // Rotate the data and normals by accumulated rotation
  205.     SbMatrix rot_mat;
  206.     prev_orientation.getValue(rot_mat);
  207.  
  208.     // transform the data
  209.     for (int j = 0; j < _num_markers; j++)
  210.     {
  211.         SbVec3f rot_left, rot_middle, rot_right;
  212.         SbVec3f rot_norm;
  213.  
  214.         // rotate the left and right data
  215.         rot_mat.multDirMatrix(_data[j].left, rot_left);
  216.         rot_mat.multDirMatrix(_data[j].middle, rot_middle);
  217.         rot_mat.multDirMatrix(_data[j].right, rot_right);
  218.  
  219.         // translate the left and right data
  220.         _data[j].left = rot_left + prev_offset;
  221.         _data[j].middle = rot_middle + prev_offset;
  222.         _data[j].right = rot_right + prev_offset;
  223.  
  224.         // median
  225.         _median_data[j].left =
  226.         _data[j].left + (1.0-STRIPE_WIDTH)*(_data[j].middle - _data[j].left);
  227.         
  228.         _median_data[j].right =
  229.         _data[j].middle + STRIPE_WIDTH*(_data[j].right - _data[j].middle);
  230.  
  231.         // terrain
  232.         _left_terrain_data[j].left = 
  233.         _data[j].left + TERRAIN_WIDTH*(_data[j].left - _data[j].middle);
  234.         _left_terrain_data[j].right = _data[j].left;
  235.         
  236.         _right_terrain_data[j].right =
  237.         _data[j].middle + TERRAIN_WIDTH*(_data[j].right - _data[j].middle);
  238.         _right_terrain_data[j].left = _data[j].right;
  239.  
  240.         // rotate, but do not translate, the normals
  241.         rot_mat.multDirMatrix(_data[j].normal, rot_norm);
  242.  
  243.         _data[j].normal = rot_norm;
  244.  
  245.         _median_data[j].left += STRIPE_HEIGHT*_data[j].normal;
  246.         _median_data[j].right += STRIPE_HEIGHT*_data[j].normal;
  247.     }
  248.  
  249.     // offset from origin to end of this stretch
  250.     _offset = _data[_num_markers-1].middle;
  251. }
  252.  
  253. // This is ugly. This is awful. This is disgusting.
  254. // But it only took 2 minutes to hack together.
  255. void Stretch::init_scenery()
  256. {
  257.     int i;
  258.     SbVec3f vec;
  259.  
  260.     vec = (_data[0].left - _data[0].middle);
  261.     vec.normalize();
  262.     vec *= SCENERY_OFFSET;
  263.     _pole_pos = _data[0].left + vec;
  264.  
  265.     i = _num_markers/3;
  266.     vec = (_data[i].right - _data[i].middle);
  267.     vec.normalize();
  268.     vec *= SCENERY_OFFSET;
  269.     _tree1_pos = _data[i].right + vec;
  270.     
  271.     i = 2*_num_markers/3;
  272.     vec = (_data[i].left - _data[i].middle);
  273.     vec.normalize();
  274.     vec *= SCENERY_OFFSET;
  275.     _tree2_pos = _data[i].left + vec;
  276. }
  277.  
  278.  
  279. // Things are rendered back to front so we don't have to use
  280. // the zbuffer
  281. void Stretch::draw(
  282.     int start_marker, int display_mode, Car * ignore_car) const
  283. {
  284.     if (_next && (_drawn++ < _ahead))
  285.         _next->draw(0, display_mode, ignore_car);
  286.  
  287.     _drawn--;
  288.  
  289.     Boolean last_backface = getbackface();
  290.     backface(TRUE);
  291.  
  292.     if (_type == CURVE)
  293.     {
  294.         draw_asphalt(start_marker, display_mode);
  295.         draw_stripes(start_marker, display_mode);
  296.         draw_terrain(start_marker, display_mode);
  297.         draw_scenery(display_mode);
  298.         draw_cars(ignore_car, display_mode);
  299.     }
  300.     else if ((_type == STRAIGHT) || (_type == CONNECT))
  301.     {
  302.         if (_hill_angle < 0.0) // hills that curve down
  303.         {
  304.             draw_terrain(start_marker, display_mode);
  305.             draw_scenery(display_mode);
  306.             draw_asphalt(start_marker, display_mode);
  307.             draw_stripes(start_marker, display_mode);
  308.             draw_cars(ignore_car, display_mode);
  309.         }
  310.         else // flats and hills that curve up
  311.         {
  312.             draw_asphalt(start_marker, display_mode);
  313.             draw_stripes(start_marker, display_mode);
  314.             draw_terrain(start_marker, display_mode);
  315.             draw_scenery(display_mode);
  316.             draw_cars(ignore_car, display_mode);
  317.         }
  318.     }
  319.     else if (_type == LOOP)
  320.     {
  321.         draw_cars(ignore_car, display_mode);
  322.         draw_asphalt(start_marker, display_mode);
  323.         draw_stripes(start_marker, display_mode);
  324.     }
  325.  
  326.     backface(last_backface);
  327. }
  328.  
  329.  
  330.  
  331. void Stretch::draw_scenery(int display_mode) const
  332. {
  333.     // draw back to front
  334.     
  335.     // draw_trees
  336.     pushmatrix();
  337.         translate(_tree2_pos[0],_tree2_pos[1],_tree2_pos[2]);
  338.         draw_tree(display_mode);
  339.     popmatrix();
  340.  
  341.     pushmatrix();
  342.         translate(_tree1_pos[0],_tree1_pos[1],_tree1_pos[2]);
  343.         draw_tree(display_mode);
  344.     popmatrix();
  345.  
  346.     // draw telephone pole
  347.     pushmatrix();
  348.         translate(_pole_pos[0],_pole_pos[1],_pole_pos[2]);
  349.         draw_pole(display_mode);
  350.     popmatrix();
  351. }
  352.  
  353.  
  354. void Stretch::draw_terrain(int start_marker, int display_mode) const
  355. {
  356.     if (display_mode == RENDER_WIREFRAME)
  357.         return; // no terrain if in wireframe mode
  358.         
  359.     int i;
  360.     
  361.     // draw terrain
  362.     cpack(GRASS_COL);
  363.  
  364.     if ((_type == STRAIGHT) && (_hill_angle == 0.0))
  365.     {
  366.         bgnpolygon();
  367.             v3f((float *)_left_terrain_data[0].left.getValue());
  368.             v3f((float *)_left_terrain_data[0].right.getValue());
  369.             v3f((float *)_left_terrain_data[_num_markers-1].right.getValue());
  370.             v3f((float *)_left_terrain_data[_num_markers-1].left.getValue());
  371.         endpolygon();
  372.  
  373.         bgnpolygon();
  374.             v3f((float *)_right_terrain_data[0].left.getValue());
  375.             v3f((float *)_right_terrain_data[0].right.getValue());
  376.             v3f((float *)_right_terrain_data[_num_markers-1].right.getValue());
  377.             v3f((float *)_right_terrain_data[_num_markers-1].left.getValue());
  378.         endpolygon();
  379.     }
  380.     else
  381.     {
  382.         int step = 2*_drawn;
  383.         if (!step) step++;
  384.         
  385.         // on left side of road
  386.         bgnqstrip();
  387.             for (i = _num_markers-1; i > start_marker; i -= step)
  388.             {
  389.                 v3f((float *)_left_terrain_data[i].right.getValue());
  390.                 v3f((float *)_left_terrain_data[i].left.getValue());
  391.             }
  392.             v3f((float *)_left_terrain_data[start_marker].right.getValue());
  393.             v3f((float *)_left_terrain_data[start_marker].left.getValue());
  394.         endqstrip();
  395.  
  396.         // on right side of road
  397.         bgnqstrip();
  398.             for (i = _num_markers-1; i > start_marker; i -= step)
  399.             {
  400.                 v3f((float *)_right_terrain_data[i].right.getValue());
  401.                 v3f((float *)_right_terrain_data[i].left.getValue());
  402.             }
  403.             v3f((float *)_right_terrain_data[start_marker].right.getValue());
  404.             v3f((float *)_right_terrain_data[start_marker].left.getValue());
  405.         endqstrip();
  406.     }
  407. }
  408.  
  409.  
  410.  
  411. void Stretch::draw_asphalt(int start_marker, int display_mode) const
  412. {
  413.     int i;
  414.         
  415.     if (display_mode == RENDER_FILLED)
  416.     {
  417.         Boolean last_backface = getbackface();
  418.     
  419.         if (_type == LOOP)
  420.         {
  421.             setpattern(HOLES);
  422.             backface(FALSE);
  423.         }
  424.  
  425.         cpack(0);
  426.         if ((_type == STRAIGHT) && (_hill_angle == 0.0))
  427.         {
  428.             bgnpolygon();
  429.                     v3f((float *)_data[0].left.getValue());
  430.                     v3f((float *)_data[0].right.getValue());
  431.                     v3f((float *)_data[_num_markers-1].right.getValue());
  432.                     v3f((float *)_data[_num_markers-1].left.getValue());
  433.             endpolygon();
  434.         }
  435.         else
  436.         {
  437.             int step = 2*_drawn;
  438.             if (!step) step++;
  439.                 
  440.             // draw back to front
  441.             bgnqstrip();
  442.                 for (i = _num_markers-1; i > start_marker; i -= step)
  443.                 {
  444.                     v3f((float *)_data[i].right.getValue());
  445.                     v3f((float *)_data[i].left.getValue());
  446.                 }
  447.                 v3f((float *)_data[start_marker].right.getValue());
  448.                 v3f((float *)_data[start_marker].left.getValue());
  449.             endqstrip();
  450.         }
  451.  
  452.         if (_type == LOOP)
  453.         {
  454.             setpattern(0);
  455.             backface(last_backface);
  456.         }
  457.     }
  458.     else // draw in wireframe
  459.     {
  460.         SbVec3f last_left, last_right;
  461.  
  462.         cpack(0xE0E0E0); // XXX
  463.         
  464.         bgnline();
  465.             v3f((float *)_data[start_marker].left.getValue());
  466.             v3f((float *)_data[start_marker].right.getValue());
  467.         endline();
  468.  
  469.         last_left = _data[start_marker].left;
  470.         last_right = _data[start_marker].right;
  471.         
  472.         for (i = start_marker + 1; i < _num_markers; i++)
  473.         {
  474.             bgnline();
  475.                 v3f((float *)_data[i].left.getValue());
  476.                 v3f((float *)_data[i].right.getValue());
  477.             endline();
  478.             
  479.             bgnline();
  480.                 v3f((float *)last_left.getValue());
  481.                 v3f((float *)_data[i].left.getValue());
  482.             endline();
  483.             
  484.             bgnline();
  485.                 v3f((float *)last_right.getValue());
  486.                 v3f((float *)_data[i].right.getValue());
  487.             endline();
  488.             
  489.             last_left = _data[i].left;
  490.             last_right = _data[i].right;
  491.         }
  492.     }
  493. }
  494.  
  495.  
  496.  
  497.  
  498. void Stretch::draw_stripes(int start_marker, int display_mode) const
  499. {
  500.     int i;
  501.  
  502.     // always draw stripes starting on an even marker
  503.     if (start_marker%2)
  504.         start_marker++;
  505.         
  506.     cpack(YELLOW_ASPHALT_COL);
  507.     for (i = start_marker; i < _num_markers - 2; i+=2)
  508.     {
  509.         if (display_mode == RENDER_FILLED)
  510.         {
  511.             bgnpolygon();
  512.                 v3f((float *)_median_data[i].left.getValue());
  513.                 v3f((float *)_median_data[i].right.getValue());
  514.                 v3f((float *)_median_data[i+1].right.getValue());
  515.                 v3f((float *)_median_data[i+1].left.getValue());
  516.             endpolygon();
  517.         }
  518.         else
  519.         {
  520.             bgnclosedline();
  521.                 v3f((float *)_median_data[i].left.getValue());
  522.                 v3f((float *)_median_data[i].right.getValue());
  523.                 v3f((float *)_median_data[i+1].right.getValue());
  524.                 v3f((float *)_median_data[i+1].left.getValue());
  525.             endclosedline();
  526.         }
  527.     }
  528. }
  529.  
  530.  
  531. void Stretch::draw_cars(Car * ignore_car, int mode) const
  532. {
  533.     for (int i = 0; i < _car_list->length(); i++)
  534.     {
  535.         Car * car = (Car *)(* _car_list)[i];
  536.  
  537.         if (car != ignore_car)
  538.         {
  539.             pushmatrix();
  540.             
  541.             const SbVec3f car_pos = car->get_dynamics()->get_car_position();
  542.             translate(car_pos[0], car_pos[1], car_pos[2]);
  543.  
  544.             SbVec3f axis;
  545.             float angle;
  546.  
  547.             // turn the quaternion into a rotation matrix
  548.             car->get_dynamics()->get_view_orientation().getValue(axis, angle);
  549.                     
  550.             // Note negative angle! Looking at car, not from car
  551.             // XXX (at least I think that's why it has to be negative !)
  552.             SbRotation quat(axis, -angle); 
  553.             SbMatrix orientation;
  554.             orientation.setRotate(quat);
  555.             multmatrix((Matrix) &orientation[0][0]);
  556.  
  557.             car->draw(mode);
  558.         
  559.             popmatrix();
  560.         }
  561.     }
  562. }
  563.  
  564.  
  565.  
  566. // For the given marker, returns the
  567. // next stretch and the next marker.
  568. //
  569. // The next marker will never be the last marker on
  570. // stretch. Instead it will be the zeroth marker on
  571. // the next stretch.
  572. const Stretch * Stretch::get_next_stretch(
  573.     int marker,    int &next_marker) const
  574. {
  575.     Stretch *result;
  576.     
  577.     if (marker == (_num_markers - 2))
  578.     {
  579.         if (_next)
  580.         {
  581.             result = _next;
  582.             next_marker = 0;
  583.         }
  584.         else
  585.         {
  586.             fprintf(stderr,"Reached end of road\n");
  587.             exit(-1);
  588.         }
  589.     }
  590.     else
  591.     {
  592.         result = (Stretch *) this;
  593.         next_marker = marker + 1;
  594.     }
  595.  
  596.     return result;
  597. }
  598.  
  599.  
  600. // For the given marker, returns the
  601. // next stretch and the next marker.
  602. //
  603. // The next marker will never be the last marker on
  604. // stretch. Instead it will be the zeroth marker on
  605. // the next stretch.
  606. const Stretch * Stretch::get_prev_stretch(
  607.     int marker,    int &prev_marker) const
  608. {
  609.     Stretch *result;
  610.     
  611.     if (marker == 0)
  612.     {
  613.         if (_prev)
  614.         {
  615.             result = _prev;
  616.             prev_marker = _prev->get_count() - 2;
  617.         }
  618.         else
  619.         {
  620.             fprintf(stderr,"Reached beginning of road\n");
  621.             exit(-1);
  622.         }
  623.     }
  624.     else
  625.     {
  626.         result = (Stretch *) this;
  627.         prev_marker = marker - 1;
  628.     }
  629.  
  630.     return result;
  631. }
  632.  
  633.  
  634. // For this stretch, returns a (not necessarily unit) vector specifying 
  635. // the forward road direction from the given marker to the next marker down
  636. // the SIDE side of the road. SIDE = LEFT, MIDDLE or RIGHT
  637. const SbVec3f Stretch::get_direction(int marker, int side) const
  638. {
  639.     SbVec3f d1, d2;
  640.  
  641.     int next_marker;
  642.     const Stretch *next_stretch = 
  643.         this->get_next_stretch(marker, next_marker);
  644.     
  645.     switch (side)
  646.     {
  647.         case LEFT:
  648.             d1 = _data[marker].left;
  649.             d2 = next_stretch->_data[next_marker].left;
  650.             break;
  651.             
  652.         case MIDDLE:
  653.             d1 = _data[marker].middle;
  654.             d2 = next_stretch->_data[next_marker].middle;
  655.             break;
  656.             
  657.         case RIGHT:
  658.             d1 = _data[marker].right;
  659.             d2 = next_stretch->_data[next_marker].right;
  660.             break;
  661.     }
  662.         
  663.     return (d2 - d1);
  664. }
  665.  
  666.  
  667. // returns a (not necessarily unit) vector specifying the side
  668. // road direction at the given marker from right to left (side == RIGHT)
  669. // or left to right (side == LEFT)
  670. const SbVec3f Stretch::get_side_direction(int marker, int side) const
  671. {
  672.     SbVec3f l = _data[marker].left;
  673.     SbVec3f r = _data[marker].right;
  674.  
  675.     if (side == RIGHT)
  676.         return (l - r);
  677.     else
  678.         return (r - l);
  679. }
  680.  
  681. // this can be overridden by subclasses (like the Curve class)
  682. // this method really only works for straights and straight hills
  683. //
  684. // Returns TRUE if position is on next marker, false if on this marker
  685. Boolean Stretch::get_marker_offset(
  686.     int marker,                // current marker
  687.     const SbVec3f position, // current position
  688.     float *new_offset)        // new offset return, 0.0 - 1.0
  689. {
  690.  
  691. //printf("  marker %d\n",marker);
  692. //printf("  position "); print_vec(position);
  693.     SbVec3f forward_vec = this->get_direction(marker,MIDDLE);
  694.     float forward_length = forward_vec.length();
  695. //printf("  forward length %f, vec "); print_vec(forward_vec);
  696.     SbVec3f car_vec = position - _data[marker].middle;
  697. //printf("  car vec "); print_vec(car_vec);
  698.     float angle = angle_between(forward_vec, car_vec);
  699. //printf("  angle %f\n",angle);
  700.     
  701.     SbVec3f proj_vec = project(car_vec, forward_vec);
  702.     float proj_length = proj_vec.length();
  703. //printf("  proj_length %f, vec ", proj_length); print_vec(proj_vec);
  704.  
  705.     if (proj_length >= forward_length)
  706.     {
  707.         // must have gone on to next segment or we're going backward's!
  708.         *new_offset = (proj_length - forward_length)/forward_length;
  709.  
  710. //printf("  Returning TRUE\n");
  711.  
  712.         // don't go on to next segment if pointing backwards
  713.         if (angle <= M_PI/2.0)
  714.             return TRUE;
  715.         else
  716.         {
  717.             printf("Wrong Way!\n");
  718.             return FALSE;
  719.         }
  720.     }
  721.     else
  722.     {
  723.         *new_offset = proj_length/forward_length;
  724.  
  725. //printf("  Returning FALSE\n");
  726.  
  727.         return FALSE;
  728.     }
  729. }
  730.  
  731.  
  732. // Returns the middle of the LEFT or RIGHT side of the
  733. // road at the given marker
  734. SbVec3f Stretch::road_pos(int side, int marker) const
  735. {
  736.     if (side == RIGHT)
  737.         return .25*this->get_left(marker) + .75*this->get_right(marker);
  738.     else if (side == LEFT)
  739.         return .75*this->get_left(marker) + .25*this->get_right(marker);
  740.     else
  741.     {
  742.         fprintf(stderr, "Stretch::road_pos illegal side %d\n",side);
  743.         exit(-1);
  744.     }
  745. }
  746.  
  747.